﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;
using System.Windows.Controls;

namespace FileTranslator
{
    // 包装了以下DataTable，使得弥补DataTable无法自动填充index的缺陷
    public class DataTableWrapper : IDisposable
    {
        private DataView innerTable;
        public DataView InnerTable
        {
            get
            {
                return innerTable;
            }
            set
            {
                innerTable = value;
            }
        }

        // DataTableWrapper所在的DataContainter的数据验证器
        public ConstraintHelper CommonConstraintHelp { get; set; }

        // 此DataTableWrapper特有的数据验证期
        public ConstraintHelper ConstraintHelp { get; set; }

        public DataTableWrapper(ConstraintHelper ch)
        {
            if (ch == null)
            {
                // TODO: Log down
                throw new System.Exception("Constrainter helper can not be null");
            }
            CommonConstraintHelp = ch;
        }

        public void AddConstraint(ConstraintHint constraint)
        {
            if (ConstraintHelp != null)
            {
                ConstraintHelp.AddConstraint(constraint);
            }
        }

        public void RemoveConstraint(ConstraintHint constraint)
        {
            if (ConstraintHelp != null)
            {
                ConstraintHelp.RemoveConstraint(constraint);
            }
        }

        public void Dispose()
        {
            if (InnerTable != null)
            {
                InnerTable.Dispose();
            }
        }

        public virtual bool VerifyConstraint()
        {
            if (InnerTable == null)
            {
                return false;
            }

            bool result = true;
            if (CommonConstraintHelp != null)
            {
                result &= CommonConstraintHelp.Verify(InnerTable);
            }
            if (ConstraintHelp != null)
            {
                result &= ConstraintHelp.Verify(InnerTable);
            }

            return result;
        }

        // dump到一个DataTable对象，使得指定的字段依次有序
        public DataTable DumpToDataTable()
        {
            if (InnerTable == null)
            {
                return null;
            }

            return InnerTable.ToTable();
        }  

        // 获得指定行的row以及（如果需要的话）获得表结构的内容
        public string[] GetRow(int position)
        {
            if (InnerTable == null)
            {
                return null;
            }

            DataTable tempTable = InnerTable.ToTable();

            if (position < 0 || position > tempTable.Rows.Count)
            {
                return null;
            }

            string[] rowInfo = new string[tempTable.Columns.Count];
            rowInfo = (string[])tempTable.Rows[position].ItemArray.Clone();
            
            return rowInfo;
        }

        // 获得指定行的row以及（如果需要的话）获得表结构的内容
        public DataRowView GetRowView(int position)
        {
            if (InnerTable == null)
            {
                return null;
            }

            if (position < 0 || position > InnerTable.Count)
            {
                return null;
            }

            return InnerTable[position];
        }

        //根据keyword的内容搜索basedColName列的内容，返回符合要求的第一行索引。支持正则匹配
        public int FindRowByColName(string basedColName, string keyword)
        {
            // 首先查看是否有指定列的存在
            if (InnerTable.Table.Columns.Contains(basedColName) == false)
            {
                // TODO: log
                throw new ArgumentException("Specified column not found");
            }

            Regex reg = new Regex(keyword);
            
            for (int i = 0; i < InnerTable.Count; i++)
            {
                if (reg.Match(InnerTable[i][basedColName].ToString()).Success == true)
                {
                    return i;
                }
            }

            return -1;
        }

        public DataColumn[] GetColumnSchema()
        {
            if (InnerTable == null)
            {
                return null;
            }

            DataColumn[] dca = new DataColumn[InnerTable.Table.Columns.Count];
            InnerTable.Table.Columns.CopyTo(dca, 0);

            return dca;
        }

        // position从0开始计算,增加一个现有行
        public virtual bool InsertAt(int position, DataRow rd)
        {
            if( rd == null || SchemaCompare(rd) == false 
                || InnerTable == null || VerifyIndex(position) == false)
            {
                return false;
            }

            int index = 0;
            if (position == InnerTable.Count && position == 0)
            {
                // 空表，插在整张表的最后
                DataRowView drv = InnerTable.AddNew();
                Array.Copy(rd.ItemArray, drv.Row.ItemArray, rd.ItemArray.Length);
                return true;
            }

            if (position == InnerTable.Count)
            {
                // 插在表的最后
                index = InnerTable.Table.Rows.IndexOf(InnerTable[position - 1].Row) + 1;
            }
            else
            {
                index = InnerTable.Table.Rows.IndexOf(InnerTable[position].Row);
            }
            // 具体的插入工作
            InnerTable.Table.Rows.InsertAt(rd, index);

            // 实现约束修正
            this.Fix(InnerTable, position);

            return true;
        }

        // position从0开始计算,增加一个空行
        public virtual bool InsertAt(int position)
        {
            if (InnerTable == null)
            {
                return false;
            }

            if (position > InnerTable.Count)
            {
                position = InnerTable.Count;
            }

            if (position < 0)
            {
                position = 0;
            }

            DataRow rdNew = InnerTable.Table.NewRow();
            // 清空整行
            for (int i = 0; i < InnerTable.Table.Columns.Count; i++ )
            {
                try
                {
                    rdNew[i] = "";
                }
                catch (ArgumentException)
                {
                    rdNew[i] = 0;
                }
            }
            
            // 按照约束填充一行
            this.Fix(rdNew, position);

            return this.InsertAt(position, rdNew);
        }

        public virtual bool Delete(int position)
        {
            if (InnerTable == null || VerifyIndex(position) == false)
            {
                return false;
            }

            InnerTable.Table.Rows.RemoveAt(InnerTable.Table.Rows.IndexOf(InnerTable[position].Row));

            this.Fix(InnerTable, Math.Max(position - 1, 0));

            return true;
        }

        public virtual bool Delete(DataRow dr)
        {
            if (InnerTable == null)
            {
                return false;
            }

            int position = InnerTable.Table.Rows.IndexOf(dr);

            return Delete(position);
        }

        public virtual bool Change(int position, DataRow newDataRow)
        {
            if (SchemaCompare(newDataRow) == false || InnerTable == null 
                || newDataRow == null || VerifyIndex(position) == false)
            {
                return false;
            }

            InnerTable[position].BeginEdit();
            for (int i = 0; i < newDataRow.ItemArray.Length; i++)
            {
                InnerTable[position][i] = newDataRow[i];
            }
            InnerTable[position].EndEdit();

            this.Fix(InnerTable[position].Row, position);

            return true;
        }

        // 两个参数都是针对自己的DataView而言，而非整张表的index
        public virtual bool Swap(int index1, int index2)
        {
            if (index1 > index2)
            {
                return Swap(index2, index1);
            }

            if (index1 == index2)
            {
                return true;
            }

            if (index1 < 0 || index2 >= InnerTable.Count || InnerTable == null)
            {
                return false;
            }
    
            DataRow dr = InnerTable.Table.NewRow();   
            dr.ItemArray = InnerTable[index1].Row.ItemArray;

            InnerTable[index1].Row.ItemArray = InnerTable[index2].Row.ItemArray;
            InnerTable[index2].Row.ItemArray = dr.ItemArray;

            // 因为主表有对rowchanged时间进行约束检查，所以这里不再需要

            this.Fix(InnerTable, index1);
            this.Fix(InnerTable, index2);

            return true;
        }

        // offset表示要移动的量，正数表示向下移动，负数表示向上移动
        public virtual bool Move(int index, int offset)
        {
            if (VerifyIndex(index) == false || VerifyIndexForMove(index + offset) == false || InnerTable == null)
            {
                return false;
            }

            int dir = offset / Math.Abs(offset);
            
            for (int i = 0; i < Math.Abs(offset); i++)
            {
                Swap(index + i * dir, index + i* dir + dir);
            }

            return true;
        }

        // 获取可以供ProptyGrid控件所使用的数据源
        public virtual DataRowForPropGrid GetDataRowForPropGridUse(int index)
        {
            if (VerifyIndex(index) == true)
            {
                return new DataRowForPropGrid(InnerTable[index].Row, CommonConstraintHelp);
            }
            else
            {
                return null;
            }
            
        }

        protected bool VerifyIndex(int position)
        {
            return !(position < 0 || position > InnerTable.Count);
        }

        protected bool VerifyIndexForMove(int position)
        {
            return !(position < 0 || position >= InnerTable.Count);
        }

        protected bool SchemaCompare(DataRow rd)
        {
            if (rd == null)
            {
                return false;
            }

            DataColumnCollection rowColumns = rd.Table.Columns;
            DataColumnCollection innerTabelColumns = InnerTable.Table.Columns;

            if (rowColumns.Count != innerTabelColumns.Count)
            {
                return false;
            }

            for (int i = 0; i < rowColumns.Count; i++)
            {
                if (!(rowColumns[i].Caption == innerTabelColumns[i].Caption
                    && rowColumns[i].DataType.Equals(innerTabelColumns[i].DataType) == true))
                {
                    return false;
                }
            }

            return true;
        }

        // 指定的DataRowView在本DataView中的位置（从0开始）
        public int GetIndexFromCurrentDataView(DataRowView drv)
        {
            int index = 0;
            foreach (DataRowView myDataRowView in InnerTable)
            {
                if (myDataRowView.Row.Equals(drv.Row) )
                {
                    return index;
                }
                
                index++;
            }

            return -1;
        }

        protected virtual void Fix(DataRow dr, int position)
        {
            if (CommonConstraintHelp != null)
            {
                CommonConstraintHelp.Fix(dr, position);
            }
            if (ConstraintHelp != null)
            {
                ConstraintHelp.Fix(dr, position);
            }
        }

        protected virtual void Fix(DataView dv, int position)
        {
            if (CommonConstraintHelp != null)
            {
                CommonConstraintHelp.Fix(dv, position);
            }
            if (ConstraintHelp != null)
            {
                ConstraintHelp.Fix(dv, position);
            }
        }
    }
}
